package com.bing.jh.controller;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.text.CharSequenceUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.bing.bingPro.common.BaseResult;
import com.bing.bingPro.entity.TSgccPowerCutNotice;
import com.bing.bingPro.mapper.TSgccPowerCutNoticeMapper;
import com.bing.jh.entity.TSgccPowerStats;
import com.bing.jh.mapper.TSgccPowerStatsMapper;
import lombok.extern.slf4j.Slf4j;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.net.ssl.*;
import java.io.IOException;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.time.LocalDate;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

@Slf4j
@RestController
public class TestController {
    @Resource
    private TSgccPowerStatsMapper tSgccPowerStatsMapper;

    @Resource
    private TSgccPowerCutNoticeMapper sgccPowerCutNoticeMapper;


    @PostMapping("sgcc")
    public BaseResult<String> list() throws IOException, NoSuchAlgorithmException, KeyManagementException {
        TrustManager[] trustAllCertificates = new TrustManager[]{
                new X509TrustManager() {
                    public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                        return null;
                    }

                    public void checkClientTrusted(
                            java.security.cert.X509Certificate[] certs, String authType) {
                    }

                    public void checkServerTrusted(
                            java.security.cert.X509Certificate[] certs, String authType) {
                    }
                }
        };

        SSLContext sc = SSLContext.getInstance("SSL");
        sc.init(null, trustAllCertificates, new java.security.SecureRandom());
        HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());

        HostnameVerifier allHostsValid = (hostname, session) -> true;

        HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);

        //读取网页区县ID
        String url = "https://www.jdianfei.com/8458.html";
        tSgccPowerStatsMapper.delete(Wrappers.lambdaQuery(TSgccPowerStats.class)
                .eq(TSgccPowerStats::getStats, 0)
                .isNull(TSgccPowerStats::getRigionId));
        List<TSgccPowerStats> list = tSgccPowerStatsMapper.selectList(null);
        //获取网页内容
        Document doc = Jsoup.connect(url).get();
        // 排除包含图片的段落
        Elements elements = doc.select("div.article_content p:not(:has(img))");
        String[] provinceList = {
                "<br>【北京】<a href=\"https://www.jdianfei.com/tags-24.html\" target=\"_blank\">北京</a><br>",
                "<br>【重庆】<a href=\"https://www.jdianfei.com/tags-84.html\" target=\"_blank\">重庆</a><br>"
        };

        for (Element element : elements) {
            for (String item : provinceList) {
                element.append(item);
            }
        }
        for (Element element : elements) {
            // 使用<br>分割不同省份和城市数据
            String[] provincetCityData = element.html().split("<br>");

            for (String data : provincetCityData) {
                if (data.trim().isEmpty()) continue;

                // 提取省份名称
                String provinceName = data.substring(data.indexOf("【") + 1, data.indexOf("】")).trim();

                // 解析剩下的城市信息
                String cityData = data.substring(data.indexOf("】") + 1);
                Document cityDoc = Jsoup.parse(cityData);
                // 提取所有链接城市
                Elements links = cityDoc.select("a");

                // 存储已处理过的链接城市名称，避免重复添加
                Set<String> processedCities = new HashSet<>();

                for (Element link : links) {
                    String cityName = link.text().trim();
                    // 将链接城市加入集合
                    processedCities.add(cityName);

                    Integer cityId = Integer.valueOf(link.attr("href").replaceAll(".*tags-(\\d+).html.*", "$1"));

                    // 获取链接中的内容
                    String linkUrl = link.attr("href");
                    boolean hasNextPage;
                    String urls = linkUrl;
                    do {
                        Document linkDoc = Jsoup.connect(urls).get();
                        Elements regionElements = linkDoc.select("div#main ul li h2 a");
                        for (Element regionElement : regionElements) {
                            Integer regionId = Integer.valueOf(regionElement.attr("href").replaceAll(".*jdianfei.com/(\\d+).html.*", "$1"));
                            addCity(provinceName, cityName, cityId, regionId, list);
                        }
                        // 处理分页
                        Elements pagebarElements = linkDoc.select("div.pagebar a");
                        hasNextPage = false;
                        for (Element pagebarElement : pagebarElements) {
                            if (pagebarElement.hasClass("next")) {
                                hasNextPage = true;
                                urls = pagebarElement.attr("href");
                                break;
                            }
                        }

                    } while (hasNextPage);
                }

                // 处理非链接城市
                for (String cityName : cityDoc.text().split("\\s+")) {
                    // 跳过非城市文本
                    if (cityName.contains("【") || cityName.isEmpty()) continue;
                    cityName = cityName.trim();
                    if (!processedCities.contains(cityName)) {
                        // 添加非链接的城市
                        addCity(provinceName, cityName, null, null, list);
                    }
                }
            }
        }

        //进行数据入库
        List<TSgccPowerStats> sgccPowerStatsList = tSgccPowerStatsMapper.selectList(null).stream()
                .filter(stats -> stats.getStats() == 0)
                .filter(stats -> stats.getRigionId() != null)
                .collect(Collectors.toList());
        if (CollUtil.isNotEmpty(sgccPowerStatsList)) {
            sgccPowerStatsList.forEach(tSgccPowerStatsList -> {
                if (tSgccPowerStatsList.getRigionId() != null) {
                    String baseUrl = "https://www.jdianfei.com/" + tSgccPowerStatsList.getRigionId() + ".html";
                    int maxProcessRetryCount = 3; // 限制最大重试次数
                    int processRetryCount = 0;

                    while (processRetryCount < maxProcessRetryCount) {
                        boolean retryProcess = false;

                        // 重试机制
                        int retryCount = 3;
                        while (retryCount > 0) {
                            try {
                                Document noticeDoc = Jsoup.connect(baseUrl)
                                        .timeout(5000) // 设置超时时间为5秒
                                        .get();
                                Element mainContainer = noticeDoc.selectFirst("div.main.container");

                                // 处理页面内容
                                if (mainContainer != null) {
                                    // 提取cityName和regionName
                                    Elements tags = mainContainer.select("span.tag a");
                                    if (tags.size() >= 2) {
                                        String cityName = tags.get(0).text().trim();
                                        if (cityName.endsWith("停电通知")) {
                                            cityName = cityName.substring(0, cityName.length() - 4);
                                        }
                                        String regionName = tags.get(1).text().trim();

                                        // 提取停电信息
                                        Element articleContent = mainContainer.selectFirst("div.article_content");
                                        if (articleContent != null) {
                                            Elements bElements = articleContent.select("b");
                                            for (Element bElement : bElements) {
                                                String reach = null, startTime = null, endTime = null, line = null, notice = null, transformerDistrict = null;

                                                Element reachElement = articleContent.selectFirst("b:contains(停电范围：)");
                                                if (reachElement != null) {
                                                    reach = reachElement.text().replace("停电范围：", "").trim();
                                                }

                                                Element sibling = bElement.nextElementSibling();
                                                while (sibling != null && sibling.tagName().equals("br") && !sibling.tagName().equals("a")) {
                                                    String text = sibling.previousSibling() != null ? sibling.previousSibling().toString().trim() : "";
                                                    if (CharSequenceUtil.isEmpty(text)) break;
                                                    if (text.contains("计划停电时间：检修开始时间：")) {
                                                        startTime = text.replace("计划停电时间：检修开始时间：", "").trim();
                                                    } else if (text.contains("预计送电时间：预计结束时间：")) {
                                                        endTime = text.replace("预计送电时间：预计结束时间：", "").trim();
                                                    } else if (text.contains("停电线路：")) {
                                                        line = text.replace("停电线路：", "").trim();
                                                    } else if (text.contains("停电台区：")) {
                                                        transformerDistrict = text.replace("停电台区：", "").trim();
                                                    } else if (text.contains("预计送电时间：")) {
                                                        endTime = text.replace("预计送电时间：", "").trim();
                                                    } else if (text.contains("计划停电时间：")) {
                                                        startTime = text.replace("计划停电时间：", "").trim();
                                                    } else if (text.contains("地方有停电通知")) {
                                                        notice = text.trim();
                                                    }
                                                    sibling = sibling.nextElementSibling();
                                                    if (sibling != null && sibling.tagName().contains("a")) {
                                                        sibling = sibling.nextElementSibling();
                                                    }
                                                }

                                                String text = bElement.text().trim();
                                                if (CharSequenceUtil.isNotEmpty(text) && (!text.contains("查询") || text.contains("热线"))) {
                                                    if (CharSequenceUtil.isEmpty(notice)) {
                                                        Element noticeElement = articleContent.selectFirst("div:contains(地方有停电通知)");
                                                        if (noticeElement != null) {
                                                            String texts = noticeElement.text().trim();
                                                            String[] cityNames = {cityName, cityName.length() > 1 ? cityName.substring(0, cityName.length() - 1) : cityName};
                                                            String[] regionNames = {regionName, regionName.length() > 1 ? regionName.substring(0, regionName.length() - 1) : regionName};
                                                            String latestNotice = "";

                                                            boolean found = false;
                                                            for (String cn : cityNames) {
                                                                for (String rn : regionNames) {
                                                                    String pattern = cn + "(?:市|区|州|县)" + rn + "(?:市|区|县)(?:(?!公司|宾馆|安文).)*?" +
                                                                            "\\d{4}年\\d{1,2}月\\d{1,2}日到\\d{4}年\\d{1,2}月\\d{1,2}日一共有以上\\d+个地方有停电通知。";
                                                                    Pattern compiledPattern = Pattern.compile(pattern);
                                                                    Matcher matcher = compiledPattern.matcher(texts);

                                                                    while (matcher.find()) {
                                                                        latestNotice = matcher.group().trim();
                                                                        if (latestNotice.contains(cn) && latestNotice.contains(rn + "市")) {
                                                                            latestNotice = latestNotice.replace(cn + rn, "").trim();
                                                                        }
                                                                    }

                                                                    if (!latestNotice.isEmpty()) {
                                                                        found = true;
                                                                        break;
                                                                    }
                                                                }
                                                                if (found) break;
                                                            }

                                                            if (!latestNotice.isEmpty()) {
                                                                String[] parts = latestNotice.split("[,\\s]");
                                                                notice = parts[parts.length - 1].trim();
                                                            }
                                                        }
                                                    }

                                                    TSgccPowerCutNotice noticeObj = new TSgccPowerCutNotice();
                                                    noticeObj.setCityName(cityName);
                                                    noticeObj.setProvinceName(tSgccPowerStatsList.getProvince());
                                                    noticeObj.setRegionName(regionName);
                                                    noticeObj.setReach(reach);
                                                    // 检查startTime，如果为空则重新执行流程
                                                    if (CharSequenceUtil.isEmpty(startTime)) {
                                                        retryProcess = true;
                                                        break;
                                                    }
                                                    noticeObj.setStartTime(startTime);
                                                    if (Objects.equals(endTime, "")) {
                                                        endTime = null;
                                                    }
                                                    noticeObj.setEndTime(endTime);

                                                    noticeObj.setLine(line);
                                                    noticeObj.setTransformerDistrict(transformerDistrict);
                                                    noticeObj.setNotice(notice);
                                                    sgccPowerCutNoticeMapper.insert(noticeObj);
                                                    tSgccPowerStatsMapper.updateStatus(tSgccPowerStatsList.getRigionId());
                                                }
                                            }
                                        }
                                    }
                                }
                                // 成功获取内容，跳出重试循环
                                break;
                            } catch (IOException e) {
                                retryCount--;
                                if (retryCount == 0) {
                                    e.printStackTrace();
                                }
                            }
                        }

                        // 执行失败需要重新执行流程，设置等待以避免频繁请求
                        if (retryProcess) {
                            try {
                                Thread.sleep(1000); // 等待1秒钟
                            } catch (InterruptedException e) {
                                Thread.currentThread().interrupt();
                            }
                            processRetryCount++;
                        } else {
                            break; // 如果不需要重新执行流程，则跳出循环
                        }
                    }
                    if (processRetryCount == maxProcessRetryCount) {
                        log.info("最大重试次数已到达，地域ID为: " + tSgccPowerStatsList.getRigionId());
                    }
                }
            });
        }
        findEmptyNotice();
        return new BaseResult<>("添加成功");
    }

    private void addCity(String provinceName, String cityName, Integer cityId, Integer regionId, List<TSgccPowerStats> list) {
        TSgccPowerStats tsStats = new TSgccPowerStats();
        tsStats.setProvince(provinceName);
        tsStats.setCity(cityName);
        tsStats.setCityId(cityId);
        tsStats.setRigionId(regionId);
        tsStats.setStats(1);
        if (!list.contains(tsStats)) {
            tsStats.setStats(0);
            tSgccPowerStatsMapper.insert(tsStats);
        }
    }


   /* @PostMapping("power")
    public BaseResult<String> power() throws IOException, NoSuchAlgorithmException, KeyManagementException {
        TrustManager[] trustAllCertificates = new TrustManager[]{
                new X509TrustManager() {
                    public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                        return null;
                    }

                    public void checkClientTrusted(
                            java.security.cert.X509Certificate[] certs, String authType) {
                    }

                    public void checkServerTrusted(
                            java.security.cert.X509Certificate[] certs, String authType) {
                    }
                }
        };

        SSLContext sc = SSLContext.getInstance("SSL");
        sc.init(null, trustAllCertificates, new java.security.SecureRandom());
        HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());

        HostnameVerifier allHostsValid = (hostname, session) -> true;

        HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);

    }*/

    private void findEmptyNotice() {
        List<TSgccPowerCutNotice> tSgccPowerCutNotices = sgccPowerCutNoticeMapper.selectList(null);

        Map<String, List<TSgccPowerCutNotice>> groupedNotices = tSgccPowerCutNotices.stream()
                .collect(Collectors.groupingBy(this::timeKey));

        groupedNotices.forEach((key, notices) -> {
            // 过滤出通知为空的对象
            List<TSgccPowerCutNotice> nullNotices = notices.stream()
                    .filter(notice -> Objects.isNull(notice.getNotice()))
                    .collect(Collectors.toList());

            // 过滤出通知非空的对象
            List<TSgccPowerCutNotice> notNullNotices = notices.stream()
                    .filter(notice -> Objects.nonNull(notice.getNotice()))
                    .collect(Collectors.toList());

            // 如果存在非空通知
            if (!notNullNotices.isEmpty()) {
                TSgccPowerCutNotice referenceNotice = notNullNotices.get(0); // 取第一个非空通知作为参考通知
                // 对每个空通知执行更新操作
                nullNotices.forEach(nullNotice -> {
                    nullNotice.setNotice(referenceNotice.getNotice());
                    sgccPowerCutNoticeMapper.update(nullNotice, Wrappers.lambdaUpdate(TSgccPowerCutNotice.class)
                            .eq(TSgccPowerCutNotice::getProvinceName, nullNotice.getProvinceName())
                            .eq(TSgccPowerCutNotice::getCityName, nullNotice.getCityName())
                            .eq(TSgccPowerCutNotice::getRegionName, nullNotice.getRegionName())
                            .eq(TSgccPowerCutNotice::getStartTime, nullNotice.getStartTime())
                            .eq(TSgccPowerCutNotice::getEndTime, nullNotice.getEndTime()));
                });
            }
        });

        Map<String, List<TSgccPowerCutNotice>> groupedNoticetime = tSgccPowerCutNotices.stream()
                .collect(Collectors.groupingBy(this::generateKey));

        groupedNoticetime.forEach((key, notices) -> {
            List<TSgccPowerCutNotice> nullNotices = notices.stream()
                    .filter(notice -> Objects.isNull(notice.getNotice()))
                    .collect(Collectors.toList());

            List<TSgccPowerCutNotice> notNullNotices = notices.stream()
                    .filter(notice -> Objects.nonNull(notice.getNotice()))
                    .collect(Collectors.toList());

            if (!notNullNotices.isEmpty()) {
                TSgccPowerCutNotice referenceNotice = notNullNotices.get(0);
                nullNotices.forEach(nullNotice -> {
                    nullNotice.setNotice(referenceNotice.getNotice());
                    sgccPowerCutNoticeMapper.update(nullNotice, Wrappers.lambdaUpdate(TSgccPowerCutNotice.class)
                            .eq(TSgccPowerCutNotice::getProvinceName, nullNotice.getProvinceName())
                            .eq(TSgccPowerCutNotice::getCityName, nullNotice.getCityName())
                            .eq(TSgccPowerCutNotice::getRegionName, nullNotice.getRegionName())
                            .eq(TSgccPowerCutNotice::getStartTime, nullNotice.getStartTime())
                            .eq(TSgccPowerCutNotice::getEndTime, nullNotice.getEndTime()));
                });
            }
        });
    }

    private String timeKey(TSgccPowerCutNotice notice) {
        return notice.getProvinceName() + "_" +
                notice.getCityName() + "_" +
                notice.getRegionName() + "_" +
                notice.getStartTime().substring(0, 10);
    }

    private String generateKey(TSgccPowerCutNotice notice) {
        return notice.getProvinceName() + "_" +
                notice.getCityName() + "_" +
                notice.getRegionName() + "_";
    }

}
